package com.tangdi.production.mpcctp.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tangdi.production.mpaychl.constants.MsgCT;
import com.tangdi.production.mpaychl.dao.MpamngAgentInfMapper;
import com.tangdi.production.mpaychl.dao.MpomngPayInfMapper;
import com.tangdi.production.mpaychl.model.MpamngAgentInf;
import com.tangdi.production.mpaychl.model.MpomngPayInf;
import com.tangdi.production.mpaychl.model.MpomngPayInfExample;
import com.tangdi.production.mpaychl.service.impl.bailian.util.EnvironmentConstants;
import com.tangdi.production.mpaychl.service.impl.bailian.util.SecureUtil;
import com.tangdi.production.mpbase.constants.ExcepCode;
import com.tangdi.production.mpbase.service.OrderService;
import com.tangdi.production.mpbase.util.ObjectUtil;
import com.tangdi.production.mpbase.util.RequestUtil;
import com.tangdi.production.mpcctp.util.MD5Util;
import com.tangdi.production.mpcctp.util.MapUtils;

@Controller
public class BailianConfirmController {
	private static final Logger log = LoggerFactory.getLogger(BailianConfirmController.class);
	
	private final static String  PAY_URL = EnvironmentConstants.BASE_URL+"/pay/v2/auth_pay_confirm";
	
	@Autowired
	MpomngPayInfMapper mpomngPayInfMapper;
	
	@Autowired
	private MpamngAgentInfMapper mpamngAgentInfMapper;
	
	@Autowired
	private OrderService orderService;
	
	@ResponseBody
	@RequestMapping("pay/confirm")
	public String confirm(HttpServletRequest request) {
		try {
			Map<String, Object> paramMap = RequestUtil.getReqMap(request);
			
			MpamngAgentInf dbMpamngAgentInf = mpamngAgentInfMapper.selectByPrimaryKey("" + paramMap.get("orgNo"));
			if (null == dbMpamngAgentInf){
				throw new Exception("代理商不存在");
			}
			
			String sign = "" + paramMap.get("sign");
			log.info("原签名串:{}", sign);
			paramMap.remove("sign");
			log.info("验证串:{}", sign(paramMap, dbMpamngAgentInf.getAgentKey()));
			if (!Objects.equals(sign, sign(paramMap, dbMpamngAgentInf.getAgentKey()))){
				throw new Exception("签名不通过");
			}
			log.info("签名验证通过");
			
			Map<String,Object> queryMap = new HashMap<String,Object>();
			queryMap.put("prdOrdNo", paramMap.get("prdOrdNo"));
			Map<String,Object> prdOrdMap = orderService.getPrdOrdMap(queryMap);
			
			if (prdOrdMap == null || prdOrdMap.size() <= 0) {
				throw new Exception("订单不存在");
			}
			if (!MsgCT.ORDSTATUS_PROCESSING.equals(prdOrdMap.get("ordStatus"))){
				throw new Exception("订单状态不正确");
			}
			if (StringUtils.isBlank(""+paramMap.get("verifyCode"))){
				throw new Exception("验证码不能为空");
			}
			
			JSONObject jsonParam = JSON.parseObject("" + prdOrdMap.get("reqJson"));
			
			// 拼装参数
			String tradeRequest = getParamter("" + paramMap.get("prdOrdNo"),""+paramMap.get("verifyCode"), jsonParam);
			JSONObject jsonObject = JSON.parseObject(tradeRequest);
			tradeRequest = jsonObject.toJSONString();
			log.info("tradeRequest:{}", tradeRequest);
			//对交易请求参数进行加密
			Map<String,String> map = SecureUtil.encryptTradeInfo(EnvironmentConstants.MERCHANT_NO, tradeRequest, EnvironmentConstants.private_key, EnvironmentConstants.public_key);
			
			String response = postSend(PAY_URL, JSON.toJSONString(map));
			
			JSONObject responseJson = JSON.parseObject(response);
			
			String tradeResponse = SecureUtil.decryptTradeInfo(EnvironmentConstants.MERCHANT_NO, responseJson.getString("CER"), responseJson.getString("DATA"), responseJson.getString("SIGN"), EnvironmentConstants.private_key, EnvironmentConstants.public_key);
			log.info("tradeResponse:{}", tradeResponse);
			
			JSONObject respjson = JSON.parseObject(tradeResponse);
			
			Map<String,Object> orderCallBackMap = new HashMap<String, Object>();
			orderCallBackMap.put("prdOrdNo", prdOrdMap.get("prdOrdNo"));//订单号
			orderCallBackMap.put("ordStatus", MsgCT.ORDSTATUS_PROCESSING);
			orderCallBackMap.put("resJson", respjson.toJSONString());
			
			JSONObject reutrnJson = new JSONObject();
			if (Objects.equals("00000000", respjson.get("responseCode")) 
			 && Objects.equals("S", respjson.get("tradeStatus"))){
				
				orderCallBackMap.put("ordStatus", MsgCT.ORDSTATUS_SUCCESS);
				reutrnJson.put("code", "000000");
			} else if (Objects.equals("F", respjson.get("tradeStatus"))) {
				orderCallBackMap.put("ordStatus", MsgCT.ORDSTATUS_FAIL);
				reutrnJson.put("code", ExcepCode.EX900003);
			} else if (Objects.equals("C", respjson.get("tradeStatus"))){
				orderCallBackMap.put("ordStatus", MsgCT.ORDSTATUS_RETURNED);
				reutrnJson.put("code", ExcepCode.EX900004);			}
			else {
				reutrnJson.put("code", ExcepCode.EX900005);
			}
			
			log.info("更新平台订单[{}]", orderCallBackMap);
			orderService.prdPayCallBack(orderCallBackMap);
			
			reutrnJson.put("msg", respjson.get("responseDesc"));
			return reutrnJson.toString();
		} catch (Exception e) {
			log.error("确认支付处理失败:{}", e.getMessage(), e);
			JSONObject json = new JSONObject();
			json.put("code", ExcepCode.EX900005);
			json.put("msg", e.getMessage());
			return json.toString();
		}
	}
	
	@SuppressWarnings("resource")
	private static String postSend(String url,String argsJson) throws Exception {
		HttpClient httpclient = new DefaultHttpClient();
		System.out.println("url:"+url);
		HttpPost httpPost = new HttpPost(url);
		
		StringEntity entity = new StringEntity(argsJson);
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/text");
		httpPost.setEntity(entity);
		
		System.out.println("request:"+argsJson);
		HttpResponse response = httpclient.execute(httpPost);
		HttpEntity resEntity = response.getEntity();
        String resp = EntityUtils.toString(resEntity);
        System.out.println("response:"+resp);
        return resp;
	}
	
	private static String getParamter(String prdOrdNo, String verifyCode,Map<String, Object> paramMap){
		
		Map<String, Object> request = new HashMap<String, Object>();
		
		request.put("userNo", "" + paramMap.get("outUserNo"));
		request.put("requestTime", System.currentTimeMillis());
		request.put("requestIp", RandomUtils.nextInt(0, 256) + "." + RandomUtils.nextInt(0, 256) + "." + RandomUtils.nextInt(0, 256) + "." + RandomUtils.nextInt(0, 256));
		request.put("expiryTime","");
		request.put("outTradeNo",prdOrdNo);
		request.put("bizTradeNo","");
		request.put("bizTradeTime",System.currentTimeMillis());
		request.put("tradeAmount",paramMap.get("payAmt"));//单位为分
		request.put("tradeCurrency","CNY");
		request.put("productCode","QBPPQAN001");
		request.put("tradeCategory","");
		request.put("tradeSubject","确认支付");
		request.put("tradeInfo","aa");
		request.put("returnInfo", "");
		request.put("returnUrl",  paramMap.get("front_url") == null ? EnvironmentConstants.return_url : "" + paramMap.get("front_url"));
		request.put("notifyAddress",EnvironmentConstants.notify_url);
		request.put("extendInfo","");
		request.put("riskInfo","");
		request.put("verifyCode", verifyCode);
		request.put("bankCode","" + paramMap.get("bankCode"));
		request.put("cardType","DC");
		request.put("cardNo","" + paramMap.get("cardNo"));
		request.put("cardExp","");
		request.put("cardCvv","");
		request.put("holderName","" + paramMap.get("holderName"));
		request.put("holderIdType","IDCARD");
		request.put("holderIdNo","" + paramMap.get("holderIdNo"));
		request.put("holderMobile","" + paramMap.get("holderMobile"));
		
		return JSON.toJSONString(request);
	}
	
	private String sign(Map<String,Object> paramMap,String signKey){
        String signStr = MapUtils.getSignStrByTreeMap(paramMap, true);
        signStr += "&key=" + signKey;
        String signValue = MD5Util.digest(signStr).toUpperCase();
        return signValue;
	}
	
}
